package org.myspring.core;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.myspring.core.bean.Address;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * @author bingtao.zhong.o
 * @date 2022/9/25 8:48 下午
 */
public class ClassPathXmlApplicationContext implements ApplicationContext{
    //bean的存储位置
    private Map<String,Object> beanMap = new HashMap<>();
    /**
     * 从类路径加载配置文件
     * @param configPathXML
     */
    public ClassPathXmlApplicationContext(String configPathXML){
        try{
            //输入流指向配置文件
            InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(configPathXML);
            //解析xml
            SAXReader reader = new SAXReader();
            //获取文档对象(代表整个spring.xml文件)
            Document document = reader.read(resourceAsStream);
            //获取所有bean标签的节点
            List<Node> beans = document.selectNodes("//bean");
            //遍历所有node节点
            beans.forEach(node -> {
                Element element = (Element) node;
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
                //通过反射机制创建对象
                try{
                    Class<?> aClass = Class.forName(className);
                    Object instance = aClass.newInstance();
                    beanMap.put(id,instance);
                }catch (Exception e){
                    e.printStackTrace();
                }
            });
            //重新遍历的原因时：怕之前的bean还没有全部初始化完毕，这里遍历是给property赋值
            beans.forEach(node -> {
                Element element = (Element) node;
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
                try{
                    Class<?> clazz = Class.forName(className);
                    List<Element>  propertyElts = element.elements("property");
                    propertyElts.forEach(propertyElt->{
                        //获取属性名
                        String propertyName = propertyElt.attributeValue("name");
                        //获取ref
                        String ref = propertyElt.attributeValue("ref");
                        //获取set方法名
                        String setMethodName = "set"+ propertyName.toUpperCase().charAt(0)+ propertyName.substring(1);
                        try {
                            Method setMethod = clazz.getDeclaredMethod(setMethodName, beanMap.get(ref).getClass());
                            setMethod.invoke(beanMap.get(id),beanMap.get(ref));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                }catch (Exception e){
                    e.printStackTrace();
                }

            });
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    @Override
    public Object getBean(String beanId) {
        return beanMap.get(beanId);
    }
}
